package com.celesea.configuration.web;

import com.celesea.framework.api.HttpKit;
import com.celesea.framework.api.Tip;
import com.celesea.framework.util.StringKit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.lang.reflect.Method;

/**
 * @author JackYuan
 * @create 2017-11-01 10:11
 */
@org.springframework.web.bind.annotation.ControllerAdvice
public class ControllerAdvice implements ResponseBodyAdvice<Object> {

    @Autowired
    private WebProperties webProperties;

    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> converterType) {
        return MappingJackson2HttpMessageConverter.class.isAssignableFrom(converterType);
    }

    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        // 统一使用 HTTPKit包裹返回值
        if (o instanceof Tip) {
            return o;
        }
        if (this.apiWrapMatches(methodParameter.getMethod())) {
            return HttpKit.success(o);
        }
        return o;
    }

    public boolean apiWrapMatches(Method method) {
        if (!webProperties.isApiWrap()) {
            return false;
        }
        ApiWrap apiWrap = method.getAnnotation(ApiWrap.class);
        if (apiWrap != null) {
            return apiWrap.value();
        }

        Package pkg = method.getDeclaringClass().getPackage();
        if (pkg == null || StringKit.isEmpty(pkg.getName())) {
            return false;
        }
        return pkg.getName().startsWith(webProperties.getApiWrapPackage());
    }
}
